package top.atluofu.luofuecommerce.order.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: MyThreadConfig
 * @description: TODO
 * @author: 有罗敷的马同学
 * @datetime: 2022Year-11Month-25Day-10:22
 * @Version: 1.0
 */
@Configuration
public class MyThreadConfig {

    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
        return new ThreadPoolExecutor(pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 修改线程中的threadlocal中存的值
     *
     * @param threadLocal 需要拿取的threadlocal
     * @param thread      需要修改的线程
     * @param t           需要填充的值
     */
    @Bean
    public <T extends Object> void modifyThreadLocalValue(ThreadLocal<T> threadLocal, Thread thread, Object t) {
        //获取thread的class
        Class<? extends Thread> aClass = thread.getClass();
        try {
            // 获取thread中的threadLocals变量，即ThreadLocal.ThreadLocalMap
            Field threadLocals = aClass.getDeclaredField("threadLocals");
            threadLocals.setAccessible(true);
            // 得到具体的ThreadLocal.ThreadLocalMap
            Object o = threadLocals.get(thread);
            // 拿取ThreadLocal.ThreadLocalMap的class
            Class<?> aClass1 = o.getClass();
            //构造set函数的参数类型
            Class[] classes = {ThreadLocal.class, Object.class};
            //拿取set函数
            Method set = aClass1.getDeclaredMethod("set", classes);
            set.setAccessible(true);
            //执行set方法，此时已经修改成功了
            set.invoke(o, new Object[]{threadLocal, t});
        } catch (NoSuchFieldException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

}
